######################################################################
package Swignition::MagicInterval;
######################################################################

use Swignition::GenericParser::Utils;
use Swignition::MagicDuration;
use Swignition::uF;
use DateTime::Span;
use overload '""'=>\&to_string, '<=>'=>\&compare, 'cmp'=>\&compare;
use strict;

sub new
{
	my $class        = shift;
	my $interval_obj = shift;
	my $this         = {};
	$this->{i}       = $interval_obj;
	
	bless $this, $class;
	return $this;
}

sub compare
{
	my $this = shift;
	my $that = shift;
	$this->{string} cmp $that->{string};
}

sub parse
{
	my $class  = shift;
	my $string = shift;
	my $elem   = shift||undef;
	my $page   = shift||undef;
	my $rv     = {};
	
	if ($string =~ /^ \s* (.+) \s* \/ \s* (.+) \s* $/x)
	{
		my $one = $1;
		my $two = $2;
		
		if ($one =~ /^P/i && $two !~ /^P/i)
		{
			my $duration = Swignition::MagicDuration->parse($one, $elem, $page);
			my $before   = Swignition::uF::datetime($two);
			
			if ($duration && $before)
			{
				my $span = DateTime::Span->from_datetime_and_duration(
					duration => $duration->{d},
					before   => $before
				);
				$rv->{i} = $span if ($span);
			}			
		}
		elsif ($one !~ /^P/i && $two !~ /^P/i)
		{
			my $start    = Swignition::uF::datetime($one);
			my $before   = Swignition::uF::datetime($two, undef, $start);
			
			if ($start && $before)
			{
				my $span = DateTime::Span->from_datetimes(
					start   => $start,
					before  => $before
				);
				$rv->{i} = $span if ($span);
			}
		}
		elsif ($one !~ /^P/i && $two =~ /^P/i)
		{
			my $start    = Swignition::uF::datetime($one);
			my $duration = Swignition::MagicDuration->parse($two, $elem, $page);

			if ($duration && $start)
			{
				my $span = DateTime::Span->from_datetime_and_duration(
					duration => $duration->{d},
					start    => $start
				);
				$rv->{i} = $span if ($span);
			}			
		}
	}
	
	if (! $rv->{i})
	{
		my $duration = Swignition::MagicDuration->parse(undef, $elem, $page);
		
		my $time     = {};
		PROP: foreach my $prop (qw(start after))
		{
			my @nodes = searchClass($prop, $elem);
			NODE: foreach my $n (@nodes)
			{
				$time->{$prop} = Swignition::uF::datetime(STRINGIFY($nodes[0], undef, 1));
				last NODE if ($time->{$prop});
			}
		}
		PROP: foreach my $prop (qw(end before))
		{
			my @nodes = searchClass($prop, $elem);
			NODE: foreach my $n (@nodes)
			{
				$time->{$prop} = Swignition::uF::datetime(
					STRINGIFY($nodes[0], undef, 1),
					undef,
					($time->{start} || $time->{after})
				);
				last NODE if ($time->{$prop});
			}
		}

		if (($time->{start}||$time->{after})
		&&  ($time->{end}||$time->{before}))
		{
			my $startlabel = ($time->{start}) ? 'start' : 'after';
			my $endlabel   = ($time->{end})   ? 'end'   : 'before';
			
			my $span = DateTime::Span->from_datetimes(
				$startlabel  => ($time->{start}||$time->{after}),
				$endlabel    => ($time->{end}||$time->{before})
			);
			$rv->{i} = $span if ($span);
		}
		
		elsif (($time->{start}||$time->{after})
		&&     ($duration))
		{
			my $startlabel = ($time->{start}) ? 'start' : 'after';
			
			my $span = DateTime::Span->from_datetime_and_duration(
				$startlabel  => ($time->{start}||$time->{after}),
				duration     => $duration->{d}
			);
			$rv->{i} = $span if ($span);
		}

		elsif (($duration)
		&&     ($time->{end}||$time->{before}))
		{
			my $endlabel   = ($time->{end})   ? 'end'   : 'before';
			
			my $span = DateTime::Span->from_datetime_and_duration(
				duration     => $duration->{d},
				$endlabel    => ($time->{end}||$time->{before})
			);
			$rv->{i} = $span if ($span);
		}
		
	}

	if ($rv->{i})
	{
		$rv->{string} = $string;
		bless $rv, $class;
		return $rv;
	}
	
	return undef;
}

sub to_string
{
	my $this = shift;
	my $D    = Swignition::MagicDuration->new($this->{i}->duration);
	
	return $this->{i}->start.'/'."$D";
}

1;
